home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / zfilter.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  11.6 KB  |  432 lines

  1. /* Copyright (C) 1993, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: zfilter.c,v 1.4 2000/09/19 19:00:53 lpd Exp $ */
  20. /* Filter creation */
  21. #include "memory_.h"
  22. #include "ghost.h"
  23. #include "oper.h"
  24. #include "gsstruct.h"
  25. #include "ialloc.h"
  26. #include "idict.h"
  27. #include "idparam.h"
  28. #include "ilevel.h"        /* SubFileDecode is different in LL3 */
  29. #include "stream.h"
  30. #include "strimpl.h"
  31. #include "sfilter.h"
  32. #include "srlx.h"
  33. #include "sstring.h"
  34. #include "ifilter.h"
  35. #include "files.h"        /* for filter_open, file_d'_buffer_size */
  36.  
  37. /* <source> ASCIIHexEncode/filter <file> */
  38. /* <source> <dict> ASCIIHexEncode/filter <file> */
  39. private int
  40. zAXE(i_ctx_t *i_ctx_p)
  41. {
  42.     return filter_write_simple(i_ctx_p, &s_AXE_template);
  43. }
  44.  
  45. /* <target> ASCIIHexDecode/filter <file> */
  46. /* <target> <dict> ASCIIHexDecode/filter <file> */
  47. private int
  48. zAXD(i_ctx_t *i_ctx_p)
  49. {
  50.     return filter_read_simple(i_ctx_p, &s_AXD_template);
  51. }
  52.  
  53. /* <target> NullEncode/filter <file> */
  54. /* <target> <dict_ignored> NullEncode/filter <file> */
  55. private int
  56. zNullE(i_ctx_t *i_ctx_p)
  57. {
  58.     return filter_write_simple(i_ctx_p, &s_NullE_template);
  59. }
  60.  
  61. /* <source> <bool> PFBDecode/filter <file> */
  62. /* <source> <dict> <bool> PFBDecode/filter <file> */
  63. private int
  64. zPFBD(i_ctx_t *i_ctx_p)
  65. {
  66.     os_ptr sop = osp;
  67.     stream_PFBD_state state;
  68.  
  69.     check_type(*sop, t_boolean);
  70.     state.binary_to_hex = sop->value.boolval;
  71.     return filter_read(i_ctx_p, 1, &s_PFBD_template, (stream_state *)&state, 0);
  72. }
  73.  
  74. /* <target> PSStringEncode/filter <file> */
  75. /* <target> <dict> PSStringEncode/filter <file> */
  76. private int
  77. zPSSE(i_ctx_t *i_ctx_p)
  78. {
  79.     return filter_write_simple(i_ctx_p, &s_PSSE_template);
  80. }
  81.  
  82. /* ------ RunLength filters ------ */
  83.  
  84. /* Common setup for RLE and RLD filters. */
  85. private int
  86. rl_setup(os_ptr dop, bool * eod)
  87. {
  88.     if (r_has_type(dop, t_dictionary)) {
  89.     int code;
  90.  
  91.     check_dict_read(*dop);
  92.     if ((code = dict_bool_param(dop, "EndOfData", true, eod)) < 0)
  93.         return code;
  94.     return 1;
  95.     } else {
  96.     *eod = true;
  97.     return 0;
  98.     }
  99. }
  100.  
  101. /* <target> <record_size> RunLengthEncode/filter <file> */
  102. /* <target> <dict> <record_size> RunLengthEncode/filter <file> */
  103. private int
  104. zRLE(i_ctx_t *i_ctx_p)
  105. {
  106.     os_ptr op = osp;
  107.     stream_RLE_state state;
  108.     int code;
  109.  
  110.     check_op(2);
  111.     code = rl_setup(op - 1, &state.EndOfData);
  112.     if (code < 0)
  113.     return code;
  114.     check_int_leu(*op, max_uint);
  115.     state.record_size = op->value.intval;
  116.     return filter_write(i_ctx_p, 1, &s_RLE_template, (stream_state *) & state, 0);
  117. }
  118.  
  119. /* <source> RunLengthDecode/filter <file> */
  120. /* <source> <dict> RunLengthDecode/filter <file> */
  121. private int
  122. zRLD(i_ctx_t *i_ctx_p)
  123. {
  124.     os_ptr op = osp;
  125.     stream_RLD_state state;
  126.     int code = rl_setup(op, &state.EndOfData);
  127.  
  128.     if (code < 0)
  129.     return code;
  130.     return filter_read(i_ctx_p, 0, &s_RLD_template, (stream_state *) & state, 0);
  131. }
  132.  
  133. /* <source> <EODcount> <EODstring> SubFileDecode/filter <file> */
  134. /* <source> <dict> <EODcount> <EODstring> SubFileDecode/filter <file> */
  135. /* <source> <dict> SubFileDecode/filter <file> *//* (LL3 only) */
  136. private int
  137. zSFD(i_ctx_t *i_ctx_p)
  138. {
  139.     os_ptr op = osp;
  140.     stream_SFD_state state;
  141.     ref *sop = op;
  142.     int npop;
  143.  
  144.     if (s_SFD_template.set_defaults)
  145.     s_SFD_template.set_defaults((stream_state *)&state);
  146.     if (LL3_ENABLED && r_has_type(op, t_dictionary)) {
  147.     int count;
  148.     int code;
  149.  
  150.     check_dict_read(*op);
  151.     if ((code = dict_int_param(op, "EODCount", 0, max_int, -1, &count)) < 0)
  152.         return code;
  153.     if (dict_find_string(op, "EODString", &sop) <= 0)
  154.         return_error(e_rangecheck);
  155.     state.count = count;
  156.     npop = 0;
  157.     } else {
  158.     check_type(sop[-1], t_integer);
  159.     if (sop[-1].value.intval < 0)
  160.         return_error(e_rangecheck);
  161.     state.count = sop[-1].value.intval;
  162.     npop = 2;
  163.     }
  164.     check_read_type(*sop, t_string);
  165.     state.eod.data = sop->value.const_bytes;
  166.     state.eod.size = r_size(sop);
  167.     return filter_read(i_ctx_p, npop, &s_SFD_template,
  168.                (stream_state *)&state, r_space(sop));
  169. }
  170.  
  171. /* ------ Utilities ------ */
  172.  
  173. /* Forward references */
  174. private int filter_ensure_buf(P4(stream **, uint, gs_ref_memory_t *, bool));
  175.  
  176. /* Set up an input filter. */
  177. int
  178. filter_read(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
  179.         stream_state * st, uint space)
  180. {
  181.     os_ptr op = osp;
  182.     uint min_size = template->min_out_size + max_min_left;
  183.     uint save_space = ialloc_space(idmemory);
  184.     os_ptr sop = op - npop;
  185.     stream *s;
  186.     stream *sstrm;
  187.     bool close = false;
  188.     int code;
  189.  
  190.     /* Skip over an optional dictionary parameter. */
  191.     if (r_has_type(sop, t_dictionary)) {
  192.     check_dict_read(*sop);
  193.     if ((code = dict_bool_param(sop, "CloseSource", false, &close)) < 0)
  194.         return code;
  195.     --sop;
  196.     }
  197.     /*
  198.      * Check to make sure that the underlying data
  199.      * can function as a source for reading.
  200.      */
  201.     switch (r_type(sop)) {
  202.     case t_string:
  203.         check_read(*sop);
  204.         ialloc_set_space(idmemory, max(space, r_space(sop)));
  205.         sstrm = file_alloc_stream(imemory, "filter_read(string stream)");
  206.         if (sstrm == 0) {
  207.         code = gs_note_error(e_VMerror);
  208.         goto out;
  209.         }
  210.         sread_string(sstrm, sop->value.bytes, r_size(sop));
  211.         sstrm->is_temp = 1;
  212.         break;
  213.     case t_file:
  214.         check_read_known_file(sstrm, sop, return);
  215.         ialloc_set_space(idmemory, max(space, r_space(sop)));
  216.         goto ens;
  217.     default:
  218.         check_proc(*sop);
  219.         ialloc_set_space(idmemory, max(space, r_space(sop)));
  220.         code = sread_proc(sop, &sstrm, iimemory);
  221.         if (code < 0)
  222.         goto out;
  223.         sstrm->is_temp = 2;
  224.       ens:
  225.         code = filter_ensure_buf(&sstrm,
  226.                      template->min_in_size +
  227.                      sstrm->state->template->min_out_size,
  228.                      iimemory, false);
  229.         if (code < 0)
  230.         goto out;
  231.         break;
  232.     }
  233.     if (min_size < 128)
  234.     min_size = file_default_buffer_size;
  235.     code = filter_open("r", min_size, (ref *) sop,
  236.                &s_filter_read_procs, template, st, imemory);
  237.     if (code < 0)
  238.     goto out;
  239.     s = fptr(sop);
  240.     s->strm = sstrm;
  241.     s->close_strm = close;
  242.     pop(op - sop);
  243. out:
  244.     ialloc_set_space(idmemory, save_space);
  245.     return code;
  246. }
  247. int
  248. filter_read_simple(i_ctx_t *i_ctx_p, const stream_template * template)
  249. {
  250.     return filter_read(i_ctx_p, 0, template, NULL, 0);
  251. }
  252.  
  253. /* Set up an output filter. */
  254. int
  255. filter_write(i_ctx_t *i_ctx_p, int npop, const stream_template * template,
  256.          stream_state * st, uint space)
  257. {
  258.     os_ptr op = osp;
  259.     uint min_size = template->min_in_size + max_min_left;
  260.     uint save_space = ialloc_space(idmemory);
  261.     register os_ptr sop = op - npop;
  262.     stream *s;
  263.     stream *sstrm;
  264.     bool close = false;
  265.     int code;
  266.  
  267.     /* Skip over an optional dictionary parameter. */
  268.     if (r_has_type(sop, t_dictionary)) {
  269.     check_dict_read(*sop);
  270.     if ((code = dict_bool_param(sop, "CloseTarget", false, &close)) < 0)
  271.         return code;
  272.     --sop;
  273.     }
  274.     /*
  275.      * Check to make sure that the underlying data
  276.      * can function as a sink for writing.
  277.      */
  278.     switch (r_type(sop)) {
  279.     case t_string:
  280.         check_write(*sop);
  281.         ialloc_set_space(idmemory, max(space, r_space(sop)));
  282.         sstrm = file_alloc_stream(imemory, "filter_write(string)");
  283.         if (sstrm == 0) {
  284.         code = gs_note_error(e_VMerror);
  285.         goto out;
  286.         }
  287.         swrite_string(sstrm, sop->value.bytes, r_size(sop));
  288.         sstrm->is_temp = 1;
  289.         break;
  290.     case t_file:
  291.         check_write_known_file(sstrm, sop, return);
  292.         ialloc_set_space(idmemory, max(space, r_space(sop)));
  293.         goto ens;
  294.     default:
  295.         check_proc(*sop);
  296.         ialloc_set_space(idmemory, max(space, r_space(sop)));
  297.         code = swrite_proc(sop, &sstrm, iimemory);
  298.         if (code < 0)
  299.         goto out;
  300.         sstrm->is_temp = 2;
  301.       ens:
  302.         code = filter_ensure_buf(&sstrm,
  303.                      template->min_out_size +
  304.                      sstrm->state->template->min_in_size,
  305.                      iimemory, true);
  306.         if (code < 0)
  307.         goto out;
  308.         break;
  309.     }
  310.     if (min_size < 128)
  311.     min_size = file_default_buffer_size;
  312.     code = filter_open("w", min_size, (ref *) sop,
  313.                &s_filter_write_procs, template, st, imemory);
  314.     if (code < 0)
  315.     goto out;
  316.     s = fptr(sop);
  317.     s->strm = sstrm;
  318.     s->close_strm = close;
  319.     pop(op - sop);
  320. out:
  321.     ialloc_set_space(idmemory, save_space);
  322.     return code;
  323. }
  324. int
  325. filter_write_simple(i_ctx_t *i_ctx_p, const stream_template * template)
  326. {
  327.     return filter_write(i_ctx_p, 0, template, NULL, 0);
  328. }
  329.  
  330. /* Define a byte-at-a-time NullDecode filter for intermediate buffers. */
  331. /* (The standard NullDecode filter can read ahead too far.) */
  332. private int
  333. s_Null1D_process(stream_state * st, stream_cursor_read * pr,
  334.          stream_cursor_write * pw, bool last)
  335. {
  336.     if (pr->ptr >= pr->limit)
  337.     return 0;
  338.     if (pw->ptr >= pw->limit)
  339.     return 1;
  340.     *++(pw->ptr) = *++(pr->ptr);
  341.     return 1;
  342. }
  343. private const stream_template s_Null1D_template = {
  344.     &st_stream_state, NULL, s_Null1D_process, 1, 1
  345. };
  346.  
  347. /* Ensure a minimum buffer size for a filter. */
  348. /* This may require creating an intermediate stream. */
  349. private int
  350. filter_ensure_buf(stream ** ps, uint min_buf_size, gs_ref_memory_t *imem,
  351.           bool writing)
  352. {
  353.     stream *s = *ps;
  354.     uint min_size = min_buf_size + max_min_left;
  355.     stream *bs;
  356.     ref bsop;
  357.     int code;
  358.  
  359.     if (s->modes == 0 /* stream is closed */  || s->bsize >= min_size)
  360.     return 0;
  361.     /* Otherwise, allocate an intermediate stream. */
  362.     if (s->cbuf == 0) {
  363.     /* This is a newly created procedure stream. */
  364.     /* Just allocate a buffer for it. */
  365.     uint len = max(min_size, 128);
  366.     byte *buf = gs_alloc_bytes((gs_memory_t *)imem, len,
  367.                    "filter_ensure_buf");
  368.  
  369.     if (buf == 0)
  370.         return_error(e_VMerror);
  371.     s->cbuf = buf;
  372.     s->srptr = s->srlimit = s->swptr = buf - 1;
  373.     s->swlimit = buf - 1 + len;
  374.     s->bsize = s->cbsize = len;
  375.     return 0;
  376.     } else {
  377.     /* Allocate an intermediate stream. */
  378.     if (writing)
  379.         code = filter_open("w", min_size, &bsop, &s_filter_write_procs,
  380.                    &s_NullE_template, NULL, (gs_memory_t *)imem);
  381.     else
  382.         code = filter_open("r", min_size, &bsop, &s_filter_read_procs,
  383.                    &s_Null1D_template, NULL, (gs_memory_t *)imem);
  384.     if (code < 0)
  385.         return code;
  386.     bs = fptr(&bsop);
  387.     bs->strm = s;
  388.     bs->is_temp = 2;
  389.     *ps = bs;
  390.     return code;
  391.     }
  392. }
  393.  
  394. /* Mark a (filter) stream as temporary. */
  395. /* We define this here to avoid importing stream.h into zf*.c. */
  396. void
  397. filter_mark_temp(const ref * fop, int is_temp)
  398. {
  399.     fptr(fop)->is_temp = is_temp;
  400. }
  401.  
  402. /* Mark the source or target of a filter as temporary, and propagate */
  403. /* close_strm from the temporary stream to the filter. */
  404. void
  405. filter_mark_strm_temp(const ref * fop, int is_temp)
  406. {
  407.     stream *s = fptr(fop);
  408.     stream *strm = s->strm;
  409.  
  410.     strm->is_temp = is_temp;
  411.     s->close_strm = strm->close_strm;
  412. }
  413.  
  414. /* ------ Initialization procedure ------ */
  415.  
  416. const op_def zfilter_op_defs[] = {
  417.         /* We enter PSStringEncode and SubFileDecode (only) */
  418.         /* as separate operators. */
  419.     {"1.psstringencode", zPSSE},
  420.     {"2.subfiledecode", zSFD},
  421.     op_def_begin_filter(),
  422.     {"1ASCIIHexEncode", zAXE},
  423.     {"1ASCIIHexDecode", zAXD},
  424.     {"1NullEncode", zNullE},
  425.     {"2PFBDecode", zPFBD},
  426.     {"1PSStringEncode", zPSSE},
  427.     {"2RunLengthEncode", zRLE},
  428.     {"1RunLengthDecode", zRLD},
  429.     {"3SubFileDecode", zSFD},
  430.     op_def_end(0)
  431. };
  432.